//! $Id$
//!
//! @File   Main.h
//! @Author Johan Andersson <skagget77@gmail.com>
//! @Date   Sat Oct 03 15:16 2009
//!
//! Main.cpp.
//!

#include "PreCompile.h"
#include "IoCpp/Configuration.h"
#include "IoCpp/Container.h"

#include <iostream>


using namespace IoCpp;


struct IWeapon {
   virtual int Fire() const = 0;
};

struct ISoldier {
   virtual void Attack() const = 0;
};


class Shotgun : public IWeapon
{
public :
   Shotgun( int power ) 
      : power(power) {
   }

   int Fire() const {
      return power;
   }

private :
   int power;
};

Shotgun* ShotgunProvider( const Injector& injector ) { 
   return new Shotgun(injector.Inject<int>("Shotgun-Power"));
}


class Ranger : public ISoldier 
{
public :
   Ranger( IWeapon* weapon ) 
      : weapon(weapon) {
   }

   void Attack() const {
      std::cout << "Ranger attacks with " << weapon->Fire() << " in power!" << std::endl;
   }

private :
   IWeapon* weapon;
};

Ranger* RangerProvider( IWeapon* weapon ) { 
   return new Ranger(weapon);
}


void Configure( Configuration& config ) 
{
   // Bind constant.
   config.BindValue<int>("Shotgun-Power").ToConstant(42);

   // Bind interfaces.
   config.BindValue<IWeapon*>().ToProvider(ShotgunProvider);
   config.BindValue<ISoldier*>().ToProvider(RangerProvider);
}

IOCPP_CONFIGURATION(Configure);


int main()
{
   Container::Configure();

   ISoldier* soldier = Inject<ISoldier*>();

   soldier->Attack();
}